#include "Dialog.h"
#include "ui_Dialog.h"

#include "_Global/HTTP/HTTPRequest.h"
#include "_Global/GlobalClass.h"


#include <QJsonObject>
#include <QJsonArray>
#include <QJsonDocument>

#include <QDir>
#include <QProcess>
#include <QThread>
#include <QLibrary>
//#include <QApplication>

#include <QPushButton>
#include <QLineEdit>



Dialog::Dialog(int argc, char *argv[], QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog),
    m_Loader(argc,argv)
{
    ui->setupUi(this);

    ui->progressBar->setRange(0, 0);
    ui->progressBar->setValue(0);
    m_nShowProgress = 0;
    m_bForceRun = false;



    connect(ui->buttonAddPath, &QPushButton::clicked, this, [=](){
        qApp->addLibraryPath(ui->editPath->text());
        QStringList listStr = qApp->libraryPaths();
        for(int i = 0; i < listStr.length(); i++)
            showMessage(listStr.at(i));
    });
    connect(ui->buttonLoadLib, &QPushButton::clicked, this, [=](){
        QLibrary lib(ui->editLibName->text());
        //lib.setFileName(libName);
        if(lib.load())
            showMessage(QString("成功加载：%1").arg(lib.fileName()));
        else
            showMessage(QString("加载失败(%1)：%2").arg(lib.errorString()).arg(lib.fileName()));
    });
    connect(ui->buttonLoadLibVersion, &QPushButton::clicked, this, [=](){
        QLibrary lib(ui->editLibName->text(), ui->editLibVersion->text().toInt());
        //lib.setFileNameAndVersion(libName, ver.toInt());
        if(lib.load())
            showMessage(QString("成功加载：%1").arg(lib.fileName()));
        else
            showMessage(QString("加载失败(%1)：%2").arg(lib.errorString()).arg(lib.fileName()));
    });
    connect(ui->buttonHide, &QPushButton::clicked, this, [=](){
        this->close();
    });




    //升级完毕
    connect(&m_Updater,&Updater::s_UpdateFinished,this,[=](int code, const QString &msg)
    {
        switch(code)
        {
        case 0:
        case 1:
            {
                qDebug() << "[DEBUG]Update Success!";



                //开启，否则窗口关闭后无法关闭程序
                qDebug() << "[DEBUG]Update Success!" << QGuiApplication::quitOnLastWindowClosed();
                //QGuiApplication::setQuitOnLastWindowClosed(true);
                if((m_nShowProgress & 0b100) != 0)
                #if defined(Q_OS_ANDROID)   //android
                    this->showMaximized();
                #else
                    this->show();
                #endif

                //!!!鹰：
                //用事件的形式调用是因为，show、showMaximized和close也是以事件的形式来使用的，只要当某窗口close时会检查quitOnLastWindowClosed是否开启，如果开启且没有其他窗口show，则会退出程序（不管是否其他程序是否将要show）。
                //先让库里的程序执行，后再关闭本窗口，否则可能库窗口会自动关闭（因为还没显示的时候，程序已经检测到没有活动窗口了）。
                QMetaObject::invokeMethod(this, "RunFiles", Qt::QueuedConnection);

                if((m_nShowProgress & 0b100) == 0)
                    this->close();
            }
            break;

        default:
            updateError(msg);
        }

        qDebug() << "[Debug]Windows:" << QGuiApplication::allWindows() << QGuiApplication::topLevelWindows();
    });

    connect(&m_Updater,&Updater::s_OperateFileInfo,this,[=](QString file, Updater::_Operate_Type type, Updater::_Operate_Result result, int errorCode = 0)
    {
        showMessage(QString("%1:%2,%3,%4\r\n").arg(file).arg(type).arg(result).arg(errorCode));
    });

    connect(&m_Updater,&Updater::s_UpdateProccess,this,[=](int count, int total)
    {
        //qDebug() << "s_UpdateProccess:" << count << total;
        if(count == 0)
            ui->progressBar->setRange(0, total);
        else
            ui->progressBar->setValue(count);
    });

    connect(&m_Updater,&Updater::s_UpdateMessage,this,&Dialog::showMessage);



    int nRet = loadUpdaterConfig();
    if(nRet < 0)
    {
        QString msg = _T("配置文件读取失败(%1)！").arg(nRet);
        qCritical() << msg;
        showMessage(msg);


        //开启，否则窗口关闭后无法关闭程序
        QGuiApplication::setQuitOnLastWindowClosed(true);

        #if defined(Q_OS_ANDROID)   //android
            this->showMaximized();
        #else
            this->show();
        #endif

        return;
    }

    if((m_nShowProgress & 0b1) != 0)
#if defined(Q_OS_ANDROID)   //android
        this->showMaximized();
#else
        this->show();
#endif



#if defined(Q_OS_ANDROID)   //android
    QVariantList::const_iterator ii;
    for(ii = m_listCopyFiles.constBegin(); ii != m_listCopyFiles.constEnd(); ii++)
    {
        copyFileAndSetPermissions((ii->toString()), QFileDevice::ReadOwner | QFileDevice::WriteOwner | QFileDevice::ExeOwner);
    }
#endif



    //(new QLabel(this))->setPixmap(QPixmap(":/backgroud.jpg"));



    startUpdate();

}

Dialog::~Dialog()
{
    delete ui;
}


int Dialog::loadUpdaterConfig()
{
    QFile fileJsonConfig;
    bool bRet;


    //先从资源中载入配置json
    fileJsonConfig.setFileName(":/UpdaterConfig.json");
    bRet = fileJsonConfig.open(QIODevice::ReadOnly);
    if(!bRet)   //如果载入失败
    {
        qWarning() << "[!WARNING]Read qrc UpdaterConfig.json file failed";

        //再从文件中载入配置json
        fileJsonConfig.setFileName("./UpdaterConfig.json");
        bRet = fileJsonConfig.open(QIODevice::ReadOnly);
        if(!bRet)
        {
            qCritical() << "[!ERROR]Read UpdaterConfig.json file failed:"
                        << QFile::exists("./UpdaterConfig.json");
            return -1;
        }
    }

    QByteArray baJsonData = fileJsonConfig.readAll();
    fileJsonConfig.close();


//解析
    QJsonParseError jsonError;
    QJsonDocument doucment = QJsonDocument::fromJson(baJsonData, &jsonError);   // 转化为 JSON 文档
    if (!doucment.isNull() && (jsonError.error == QJsonParseError::NoError))    // 解析未发生错误
    {
        if (doucment.isObject())    // JSON 文档为对象
        {
            QJsonObject rootObject = doucment.object();     //转化为对象

            //读取m_strUpdateJsonURL
            if (rootObject.contains("UpdateJsonURL"))       //包含指定的 key
            {
                QJsonValue value = rootObject.value("UpdateJsonURL");  //获取指定 key 对应的 value
                if (value.isString())   //判断 value 是否为字符串
                {
                    //QString strName = value.toString();  //将 value 转化为字符串
                    m_strUpdateJsonURL = value.toString();
                }
                else
                {
                    qWarning()<<"[!WARNING]Get UpdateJsonURL FAIL!";
                    //return -2;
                }
            }
            else
            {
                qWarning()<<"[!WARNING]NO UpdateJsonURL!";
                //return -3;
            }

            //读取ShowProgress
            if (rootObject.contains("ShowProgress"))
            {
                QJsonValue value = rootObject.value("ShowProgress");
                m_nShowProgress = value.toInt();
                //qDebug()<<value.toArray().toVariantList();
            }
            else
            {
                qWarning()<<"[!WARNING]NO ShowProgress!";
                //return -4;
            }

            //读取ForceRun
            if (rootObject.contains("ForceRun"))
            {
                QJsonValue value = rootObject.value("ForceRun");
                m_bForceRun = value.toBool();
                //qDebug()<<value.toArray().toVariantList();
            }
            else
            {
                qWarning()<<"[!WARNING]NO ForceRun!";
                //return -5;
            }


            //读取m_strExecutableProgram
            if (rootObject.contains("ExecutablePrograms"))
            {
                QJsonValue value = rootObject.value("ExecutablePrograms");
                m_listExecutablePrograms = value.toArray().toVariantList();
                //qDebug()<<value.toArray().toVariantList();
                qDebug() << "[DEBUG]ExecutablePrograms:" << m_listExecutablePrograms;
            }
            else
            {
                qWarning()<<"[!WARNING]NO ExecutablePrograms!";
                //return -6;
            }

            //读取m_listDynamicLibs
            if (rootObject.contains("DynamicLibs"))
            {
                QJsonValue value = rootObject.value("DynamicLibs");
                m_listDynamicLibs = value.toArray().toVariantList();
                //QString argStr = value.toString();
                //qDebug()<<value.toArray().toVariantList();
                //m_strProgramArguments = argStr.split(' ');
                qDebug() << "[DEBUG]DynamicLibs:" << m_listDynamicLibs;
            }
            else
            {
                qWarning()<<"[!WARNING]NO DynamicLibs!";
                //return -7;
            }

#if defined(Q_OS_ANDROID)   //android
            //读取m_strExecutableProgram
            if (rootObject.contains("CopyFiles"))
            {
                QJsonValue value = rootObject.value("CopyFiles");
                m_listCopyFiles = value.toArray().toVariantList();
                //qDebug()<<value.toArray().toVariantList();
                qDebug() << "[DEBUG]CopyFiles:" << m_listCopyFiles;
            }
            else
            {
                qWarning()<<"[!WARNING]NO CopyFiles!";
                //return -8;
            }
#endif

        }
        else
        {
            qCritical()<<"[!ERROR]Json Root is not Object!";
            return -9;
        }
    }
    else
    {
        qCritical()<<"[!ERROR]Json Parse ERROR!";
        return -10;
    }

    return 0;
}

void Dialog::showMessage(QString msg)
{
    ui->MessageLabel->append(msg);
    //ui->ResultLabel->adjustSize();
    //ui->MessageLabel->adjustSize();
}

void Dialog::updateError(QString msg)
{
    qCritical() << msg;
    showMessage(msg);
    //ui->ResultLabel->adjustSize();
    //ui->MessageLabel->adjustSize();



    //开启，否则窗口关闭后无法关闭程序
    if(!m_bForceRun)
        QGuiApplication::setQuitOnLastWindowClosed(true);

    if((m_nShowProgress & 0b10) != 0)
#if defined(Q_OS_ANDROID)   //android
        this->showMaximized();
#else
        this->show();
#endif

    if(m_bForceRun)
        QMetaObject::invokeMethod(this, "RunFiles", Qt::QueuedConnection);

    if((m_nShowProgress & 0b10) == 0)
        this->close();

}

void Dialog::RunFiles()
{
//循环运行
    QVariantList::const_iterator ii;

    for(ii = m_listExecutablePrograms.constBegin(); ii != m_listExecutablePrograms.constEnd(); ii++)
    {
        QVariantMap info = ii->toMap();
        m_Loader.RunExecutableProgram(info.value("FileName").toString(), info.value("FunctionArguments").toString().split(' '));
    }

    for(ii = m_listDynamicLibs.constBegin(); ii != m_listDynamicLibs.constEnd(); ii++)
    {
        QVariantMap info = ii->toMap();
        m_Loader.RunDynamicLib(info.value("FileName").toString(), info.value("FunctionName").toString(), info.value("FunctionArguments").toString());
    }
}
